package com.ehsunbehravesh.mypasswords.gui;

import com.ehsunbehravesh.mypasswords.Logger;
import com.ehsunbehravesh.mypasswords.Utils;
import com.ehsunbehravesh.mypasswords.io.FileEncryptor;
import com.ehsunbehravesh.mypasswords.io.FileEncryptorMessage;
import com.ehsunbehravesh.mypasswords.io.FileLoader;
import com.ehsunbehravesh.mypasswords.io.FileLoaderMessage;
import com.ehsunbehravesh.mypasswords.io.FileSaver;
import com.ehsunbehravesh.mypasswords.io.FileSaverMessage;
import com.ehsunbehravesh.mypasswords.resource.ResourceLoader;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.io.File;
import java.nio.charset.Charset;
import java.util.Observable;
import java.util.Observer;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;

public class EncryptionDialog extends javax.swing.JDialog implements ActionListener, Observer {

  private JPopupMenu popMessage, popEncrypted;
  private JMenuItem mniEncryptedCopy, mniTextPaste, mniTextCopy, mniTextSelectAll, mniEncryptedSelectAll;
  private JFrame parent;
  private Byte[] contentOfFile;
  private File largeSourceFile;
  private File largeDestinationFile;

  public EncryptionDialog(JFrame parent, boolean modal) {
    super(parent, modal);
    this.parent = parent;
    initComponents();
    createComponents();
    myInitComponents();
  }

  @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jPanel2 = new javax.swing.JPanel();
        pnlStatus = new javax.swing.JPanel();
        progressBar = new javax.swing.JProgressBar();
        jTabbedPane1 = new javax.swing.JTabbedPane();
        jPanel1 = new javax.swing.JPanel();
        tlbMain = new javax.swing.JToolBar();
        btnEncrypt = new javax.swing.JButton();
        btnDecrypt = new javax.swing.JButton();
        slpMain = new javax.swing.JSplitPane();
        jScrollPane2 = new javax.swing.JScrollPane();
        txaEncrypted = new javax.swing.JTextArea();
        jScrolPane1 = new javax.swing.JScrollPane();
        txaMessage = new javax.swing.JTextArea();
        jPanel4 = new javax.swing.JPanel();
        tlbMain2 = new javax.swing.JToolBar();
        btnOpenLarge = new javax.swing.JButton();

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 100, Short.MAX_VALUE)
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 100, Short.MAX_VALUE)
        );

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("Encryptor");

        javax.swing.GroupLayout pnlStatusLayout = new javax.swing.GroupLayout(pnlStatus);
        pnlStatus.setLayout(pnlStatusLayout);
        pnlStatusLayout.setHorizontalGroup(
            pnlStatusLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnlStatusLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(progressBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        pnlStatusLayout.setVerticalGroup(
            pnlStatusLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnlStatusLayout.createSequentialGroup()
                .addComponent(progressBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jTabbedPane1.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                jTabbedPane1KeyPressed(evt);
            }
        });

        jPanel1.setLayout(new java.awt.BorderLayout());

        tlbMain.setBackground(new java.awt.Color(255, 255, 255));
        tlbMain.setFloatable(false);
        tlbMain.setRollover(true);

        btnEncrypt.setBackground(new java.awt.Color(255, 255, 255));
        btnEncrypt.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/ehsunbehravesh/mypasswords/resource/lock.png"))); // NOI18N
        btnEncrypt.setToolTipText("Encrypt");
        btnEncrypt.setFocusable(false);
        btnEncrypt.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        btnEncrypt.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnEncrypt.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnEncryptActionPerformed(evt);
            }
        });
        tlbMain.add(btnEncrypt);

        btnDecrypt.setBackground(new java.awt.Color(255, 255, 255));
        btnDecrypt.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/ehsunbehravesh/mypasswords/resource/unlock.png"))); // NOI18N
        btnDecrypt.setToolTipText("Decrypt");
        btnDecrypt.setFocusable(false);
        btnDecrypt.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        btnDecrypt.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnDecrypt.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnDecryptActionPerformed(evt);
            }
        });
        tlbMain.add(btnDecrypt);

        jPanel1.add(tlbMain, java.awt.BorderLayout.PAGE_START);

        slpMain.setBackground(new java.awt.Color(255, 255, 255));
        slpMain.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
        slpMain.setResizeWeight(0.5);

        txaEncrypted.setColumns(20);
        txaEncrypted.setEditable(false);
        txaEncrypted.setLineWrap(true);
        txaEncrypted.setRows(5);
        txaEncrypted.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                txaEncryptedMouseClicked(evt);
            }
        });
        txaEncrypted.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                txaEncryptedKeyPressed(evt);
            }
        });
        jScrollPane2.setViewportView(txaEncrypted);

        slpMain.setRightComponent(jScrollPane2);

        txaMessage.setColumns(20);
        txaMessage.setLineWrap(true);
        txaMessage.setRows(5);
        txaMessage.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                txaMessageMouseClicked(evt);
            }
        });
        txaMessage.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                txaMessageKeyPressed(evt);
            }
        });
        jScrolPane1.setViewportView(txaMessage);

        slpMain.setLeftComponent(jScrolPane1);

        jPanel1.add(slpMain, java.awt.BorderLayout.CENTER);

        jTabbedPane1.addTab("Text", jPanel1);

        tlbMain2.setBackground(new java.awt.Color(255, 255, 255));
        tlbMain2.setFloatable(false);
        tlbMain2.setRollover(true);

        btnOpenLarge.setBackground(new java.awt.Color(255, 255, 255));
        btnOpenLarge.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/ehsunbehravesh/mypasswords/resource/open.png"))); // NOI18N
        btnOpenLarge.setToolTipText("Open file");
        btnOpenLarge.setFocusable(false);
        btnOpenLarge.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        btnOpenLarge.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnOpenLarge.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnOpenLargeActionPerformed(evt);
            }
        });
        tlbMain2.add(btnOpenLarge);

        javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4);
        jPanel4.setLayout(jPanel4Layout);
        jPanel4Layout.setHorizontalGroup(
            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(tlbMain2, javax.swing.GroupLayout.DEFAULT_SIZE, 398, Short.MAX_VALUE)
        );
        jPanel4Layout.setVerticalGroup(
            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel4Layout.createSequentialGroup()
                .addComponent(tlbMain2, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(265, Short.MAX_VALUE))
        );

        jTabbedPane1.addTab("File", jPanel4);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(pnlStatus, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(jTabbedPane1)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addComponent(jTabbedPane1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(pnlStatus, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

  private void btnEncryptActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnEncryptActionPerformed
    encryptText();
  }//GEN-LAST:event_btnEncryptActionPerformed

  private void btnDecryptActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDecryptActionPerformed
    decryptText();
  }//GEN-LAST:event_btnDecryptActionPerformed

  private void txaEncryptedMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_txaEncryptedMouseClicked
    txaEncryptedMouseClick(evt);
  }//GEN-LAST:event_txaEncryptedMouseClicked

  private void txaMessageMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_txaMessageMouseClicked
    txaMessageMouseclick(evt);
  }//GEN-LAST:event_txaMessageMouseClicked

  private void btnOpenLargeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnOpenLargeActionPerformed
    openLargeFile();
  }//GEN-LAST:event_btnOpenLargeActionPerformed

  private void jTabbedPane1KeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_jTabbedPane1KeyPressed
    jTabbedPane1KeyPress(evt);
  }//GEN-LAST:event_jTabbedPane1KeyPressed

  private void txaMessageKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_txaMessageKeyPressed
    txaMessageKeyPress(evt);
  }//GEN-LAST:event_txaMessageKeyPressed

  private void txaEncryptedKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_txaEncryptedKeyPressed
    txaEncryptedKeyPress(evt);
  }//GEN-LAST:event_txaEncryptedKeyPressed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnDecrypt;
    private javax.swing.JButton btnEncrypt;
    private javax.swing.JButton btnOpenLarge;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel4;
    private javax.swing.JScrollPane jScrolPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JTabbedPane jTabbedPane1;
    private javax.swing.JPanel pnlStatus;
    private javax.swing.JProgressBar progressBar;
    private javax.swing.JSplitPane slpMain;
    private javax.swing.JToolBar tlbMain;
    private javax.swing.JToolBar tlbMain2;
    private javax.swing.JTextArea txaEncrypted;
    private javax.swing.JTextArea txaMessage;
    // End of variables declaration//GEN-END:variables

  private void myInitComponents() {
    setComponentOrientation(parent.getComponentOrientation());
    setFont(parent.getFont());
    Utils.setCenterOfParent(parent, this);
    progressBar.setVisible(false);
  }

  private void encryptText() {
    String key = getEncryptionKey();
    if (key != null) {
      try {
        String text = txaMessage.getText();
        String encrypted = Utils.encrypt(key, text);
        txaEncrypted.setText(encrypted);
      } catch (Exception ex) {
        JOptionPane.showMessageDialog(this, "Invalid encryption key!", "Error", JOptionPane.ERROR_MESSAGE);
        Logger.log(ex.getMessage());
      }
    }
  }

  private String getEncryptionKey() {
    ImageIcon icon = new ImageIcon(ResourceLoader.class.getResource("key64.png"));
    String key = (String) JOptionPane.showInputDialog(this, "Enter your encryption key (16 characters): ", "Key", JOptionPane.QUESTION_MESSAGE, icon, null, null);
    if (key != null) {
      if (key.length() != 16) {
        JOptionPane.showMessageDialog(this, "The key must be 16 characters long!", "Invalid Key", JOptionPane.WARNING_MESSAGE);
        return null;
      } else {
        return key;
      }
    }

    return null;
  }

  private void decryptText() {
    String key = getEncryptionKey();
    if (key != null) {
      try {
        String encrypted = txaMessage.getText();
        String text = Utils.decrypt(key, encrypted);
        txaEncrypted.setText(text);
      } catch (Exception ex) {
        JOptionPane.showMessageDialog(this, "Invalid encryption key!", "Error", JOptionPane.ERROR_MESSAGE);
        Logger.log(ex.getMessage());
      }
    }
  }

  private void createComponents() {
    popMessage = new JPopupMenu();
    popEncrypted = new JPopupMenu();
    mniEncryptedCopy = new JMenuItem("Copy");
    mniTextCopy = new JMenuItem("Copy");
    mniTextPaste = new JMenuItem("Paste");
    mniTextSelectAll = new JMenuItem("Select All");
    mniEncryptedSelectAll = new JMenuItem("Select All");

    popMessage.add(mniTextSelectAll);
    popMessage.add(mniTextCopy);
    popMessage.add(mniTextPaste);
    popEncrypted.add(mniEncryptedSelectAll);
    popEncrypted.add(mniEncryptedCopy);


    mniEncryptedCopy.addActionListener(this);
    mniTextPaste.addActionListener(this);
    mniTextCopy.addActionListener(this);
    mniTextSelectAll.addActionListener(this);
    mniEncryptedSelectAll.addActionListener(this);
  }

  public void actionPerformed(ActionEvent e) {
    Object source = e.getSource();

    if (source == mniTextCopy) {
      String selectedText = txaMessage.getSelectedText();
      Utils.setClipboardContents(selectedText, null);
    } else if (source == mniEncryptedCopy) {
      String selectedText = txaEncrypted.getSelectedText();
      Utils.setClipboardContents(selectedText, null);
    } else if (source == mniTextPaste) {
      String textInClipboard = Utils.getClipboardContents();
      if (textInClipboard != null && textInClipboard.length() > 0) {
        txaMessage.replaceSelection(textInClipboard);
      }
    } else if (source == mniTextSelectAll) {
      txaMessage.requestFocus();
      txaMessage.selectAll();
    } else if (source == mniEncryptedSelectAll) {
      txaEncrypted.requestFocus();
      txaEncrypted.selectAll();
    }
  }

  private void txaEncryptedMouseClick(MouseEvent evt) {
    if (SwingUtilities.isRightMouseButton(evt)) {
      String selectedText = txaEncrypted.getSelectedText();
      mniEncryptedCopy.setEnabled(selectedText != null && selectedText.length() > 0);

      popEncrypted.show(txaEncrypted, evt.getX(), evt.getY());
    }
  }

  private void txaMessageMouseclick(MouseEvent evt) {
    if (SwingUtilities.isRightMouseButton(evt)) {
      String clipboardContent = Utils.getClipboardContents();
      mniTextPaste.setEnabled(clipboardContent != null && clipboardContent.length() > 0);

      String selectedText = txaMessage.getSelectedText();
      mniTextCopy.setEnabled(selectedText != null && selectedText.length() > 0);
      popMessage.show(jScrolPane1, evt.getX(), evt.getY());
    }
  }

  private void openFile() {
    final JFileChooser fileChooser = new JFileChooser();
    int answer = fileChooser.showOpenDialog(this);

    if (answer == JFileChooser.APPROVE_OPTION) {
      File file = null;
      file = fileChooser.getSelectedFile();
      int buffersize = (int) (file.length() / 100);
      if (buffersize < 1024) {
        buffersize = 1024;
      }
      if (file.length() / 1048576 > 10) {
        JOptionPane.showMessageDialog(this, "Files greater than 10MB are not supported! Go to next tab", "Big file", JOptionPane.ERROR_MESSAGE);
      } else {
        FileLoader fileLoader = new FileLoader(file, buffersize);
        fileLoader.addObserver(this);
        Thread thread = new Thread(fileLoader);
        progressBar.setMinimum(0);
        progressBar.setMaximum((int) (file.length() / buffersize));
        progressBar.setValue(0);
        progressBar.setVisible(true);
        invalidate();
        repaint();
        thread.start();
      }
    }
  }

  public void update(Observable o, Object arg) {
    if (o instanceof FileLoader) {
      FileLoader fileLoader = (FileLoader) o;
      FileLoaderMessage message = (FileLoaderMessage) arg;
      if (message.getMessage() == FileLoaderMessage.PROGRESS) {
        progressBar.setValue(progressBar.getValue() + 1);
      } else if (message.getMessage() == FileLoaderMessage.EXCEPTION) {
        progressBar.setVisible(false);
        JOptionPane.showMessageDialog(this, message.getDescription(), "Error", JOptionPane.ERROR_MESSAGE);
      } else if (message.getMessage() == FileLoaderMessage.FINISHED) {
        progressBar.setVisible(false);
        contentOfFile = fileLoader.getContent();
      }
    } else if (o instanceof FileSaver) {
      FileSaver fileSaver = (FileSaver) o;
      FileSaverMessage message = (FileSaverMessage) arg;
      if (message.getMessage() == FileSaverMessage.PROGRESS) {
        progressBar.setValue(progressBar.getValue() + 1);
      } else if (message.getMessage() == FileSaverMessage.FINISHED) {
        JOptionPane.showMessageDialog(this, "Saved successfully!", "Saved", JOptionPane.INFORMATION_MESSAGE);
        progressBar.setVisible(false);
      } else if (message.getMessage() == FileSaverMessage.EXCEPTION) {
        progressBar.setVisible(false);
        JOptionPane.showMessageDialog(this, message.getDescription(), "Error", JOptionPane.ERROR_MESSAGE);
      }
    } else if (o instanceof FileEncryptor) {
      FileEncryptor encryptor = (FileEncryptor) o;
      FileEncryptorMessage message = (FileEncryptorMessage) arg;
      if (message.getMessage() == FileEncryptorMessage.MESSAGE_PROGRESS) {
        progressBar.setValue(progressBar.getValue() + 1);
      } else if (message.getMessage() == FileEncryptorMessage.MESSAGE_FINISHED) {
        progressBar.setVisible(false);
        JOptionPane.showMessageDialog(this, "Saved successfully!", "Saved", JOptionPane.INFORMATION_MESSAGE);        
      } else if (message.getMessage() == FileEncryptorMessage.MESSAGE_EXCEPTION_IN_READING_FILE) {
        progressBar.setVisible(false);
        JOptionPane.showMessageDialog(this, "Error happened in reading file!", "Error", JOptionPane.ERROR_MESSAGE);
        Logger.log(message.getDescription());
      } else if (message.getMessage() == FileEncryptorMessage.MESSAGE_EXCEPTION_IN_WRITING_FILE) {
        progressBar.setVisible(false);
        JOptionPane.showMessageDialog(this, "Error happened in writing file!", "Error", JOptionPane.ERROR_MESSAGE);
        Logger.log(message.getDescription());
      } else if (message.getMessage() == FileEncryptorMessage.MESSAGE_EXCEPTION_IN_ENCRYPTION) {
        progressBar.setVisible(false);
        JOptionPane.showMessageDialog(this, "Error happened in encryption!", "Error", JOptionPane.ERROR_MESSAGE);
        Logger.log(message.getDescription());
      } else if (message.getMessage() == FileEncryptorMessage.MESSAGE_EXCEPTION_IN_DECRYPTION) {
        progressBar.setVisible(false);
        JOptionPane.showMessageDialog(this, "Error happened in decryption!", "Error", JOptionPane.ERROR_MESSAGE);
        Logger.log(message.getDescription());
      } else if (message.getMessage() == FileEncryptorMessage.MESSAGE_EXCEPTION) {
        progressBar.setVisible(false);
        JOptionPane.showMessageDialog(this, "Error happened!", "Error", JOptionPane.ERROR_MESSAGE);
        Logger.log(message.getDescription());
      }
    }
  }

  private void saveEncryptFile() {
    String key = getEncryptionKey();
    if (key != null) {
      final JFileChooser fileChooser = new JFileChooser();
      int answer = fileChooser.showSaveDialog(this);

      if (answer == JFileChooser.APPROVE_OPTION) {
        File file = fileChooser.getSelectedFile();
        boolean fileIsOk = true;
        if (file.exists()) {
          answer = JOptionPane.showConfirmDialog(this, "Do you want to overwrite exisiting file?", "Warning", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
          fileIsOk = answer == JOptionPane.YES_OPTION;
        }
        if (fileIsOk) {
          try {

            // <editor-fold defaultstate="collapsed" desc="Byte[] to byte[]">              
            byte[] byteText = new byte[contentOfFile.length];
            for (int i = 0; i < byteText.length; i++) {
              byteText[i] = contentOfFile[i].byteValue();
            }
            byte[] encryptedData = Utils.encrypt(key, byteText);
            //byte[] encryptedData = byteText;
            // </editor-fold>                          
            FileSaver fileSaver = new FileSaver(file, encryptedData, 1000);
            fileSaver.addObserver(this);
            Thread thread = new Thread(fileSaver);
            progressBar.setValue(0);
            progressBar.setMaximum(encryptedData.length / 1000);
            progressBar.setVisible(true);
            thread.start();
          } catch (Exception ex) {
            JOptionPane.showMessageDialog(this, "Error occured in encryption!", "Error", JOptionPane.ERROR_MESSAGE);
            Logger.log(ex.getMessage());
          }
        }
      }
    }
  }

  private void saveDecryptFile() {
    String key = getEncryptionKey();
    if (key != null) {
      final JFileChooser fileChooser = new JFileChooser();
      int answer = fileChooser.showSaveDialog(this);

      if (answer == JFileChooser.APPROVE_OPTION) {
        File file = fileChooser.getSelectedFile();
        boolean fileIsOk = true;
        if (file.exists()) {
          answer = JOptionPane.showConfirmDialog(this, "Do you want to overwrite exisiting file?", "Warning", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
          fileIsOk = answer == JOptionPane.YES_OPTION;
        }
        if (fileIsOk) {
          try {

            // <editor-fold defaultstate="collapsed" desc="Byte[] to byte[]">              
            byte[] byteText = new byte[contentOfFile.length];
            for (int i = 0; i < byteText.length; i++) {
              byteText[i] = contentOfFile[i].byteValue();
            }
            byte[] encryptedData = Utils.decrypt(key, byteText);
            //byte[] encryptedData = byteText;
            // </editor-fold>              
            FileSaver fileSaver = new FileSaver(file, encryptedData, 1000);
            fileSaver.addObserver(this);
            Thread thread = new Thread(fileSaver);
            progressBar.setValue(0);
            progressBar.setMaximum(encryptedData.length / 1000);
            progressBar.setVisible(true);
            thread.start();
          } catch (Exception ex) {
            JOptionPane.showMessageDialog(this, "Error occured in decryption!", "Error", JOptionPane.ERROR_MESSAGE);
            Logger.log(ex.getMessage());
          }
        }
      }
    }
  }

  /*
  private void testSave(byte[] content, String filename) {
  FileOutputStream fileOutputStream = null;
  try {
  File file = new File(filename);
  fileOutputStream = new FileOutputStream(file);
  fileOutputStream.write(content);
  } catch (Exception ex) {
  System.out.println(ex.getMessage());
  } finally {
  try {
  fileOutputStream.close();
  } catch (IOException ex) {
  System.out.println(ex.getMessage());
  }
  }
  }
   */
  private void openLargeFile() {
    final JFileChooser fileChooser = new JFileChooser();
    int answer = fileChooser.showOpenDialog(this);

    if (answer == JFileChooser.APPROVE_OPTION) {
      largeSourceFile = fileChooser.getSelectedFile();
      if (largeSourceFile.exists()) {
        String strSizeOfFile = "";
        if (largeSourceFile.length() < 1000) {
          strSizeOfFile = String.format("%d bytes", largeSourceFile.length());
        } else if (largeSourceFile.length() < 1000000) {
          strSizeOfFile = String.format("%.2f kilobytes", (float) largeSourceFile.length() / 1024);
        } else if (largeSourceFile.length() < 1000000000) {
          strSizeOfFile = String.format("%.2f megabytes", (float) largeSourceFile.length() / 1048576);
        } else {
          strSizeOfFile = String.format("%.2f gigabytes", (float) largeSourceFile.length() / 1073741824);
        }
        String result = (String) JOptionPane.showInputDialog(this, String.format("<html>Size of your file is <b>%s</b>.<br/>What do you want to do with this file?</html>", strSizeOfFile), "Encryption / Decryption", JOptionPane.QUESTION_MESSAGE, null, new String[]{"Encrypt", "Decrypt"}, null);
        if (result != null) {
          answer = fileChooser.showSaveDialog(this);
          if (answer == JFileChooser.APPROVE_OPTION) {
            largeDestinationFile = fileChooser.getSelectedFile();
            boolean fileIsOk = true;
            if (largeDestinationFile.exists()) {
              answer = JOptionPane.showConfirmDialog(this, "Do you want to overwrite exisiting file?", "Warning", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
              fileIsOk = answer == JOptionPane.YES_OPTION;
            }
            if (fileIsOk) {
              String strKey = getEncryptionKey();
              if (strKey != null) {
                byte[] key = strKey.getBytes(Charset.forName("UTF8"));
                int mode = result.equalsIgnoreCase("encrypt") ? FileEncryptor.MODE_ENCRYPTION : (result.equalsIgnoreCase("decrypt") ? FileEncryptor.MODE_DECRYPTION : 0);
                if (mode != 0) {
                  int bufferSize = 2 * 1048576;
                  FileEncryptor fileEncryptor = new FileEncryptor(mode, key, largeSourceFile, largeDestinationFile, bufferSize);
                  fileEncryptor.addObserver(this);
                  progressBar.setValue(0);
                  progressBar.setMaximum((int) (largeSourceFile.length() / bufferSize));
                  progressBar.setVisible(true);
                  Thread thread = new Thread(fileEncryptor);
                  thread.start();
                }
              }
            }
          }
        }
      }
    }
  }

  private void jTabbedPane1KeyPress(KeyEvent evt) {
    int key = evt.getKeyCode();
    if (key == 27) {
      closeDialog();
    }
  }

  private void closeDialog() {
    setVisible(false);
    dispose();
  }

  private void txaMessageKeyPress(KeyEvent evt) {
    int key = evt.getKeyCode();
    if (key == 27) {
      closeDialog();
    }
  }

  private void txaEncryptedKeyPress(KeyEvent evt) {
    int key = evt.getKeyCode();
    if (key == 27) {
      closeDialog();
    }
  }
}
